package com.ruoyi.count.until;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.ruoyi.count.domain.ClassScoretemp;
import com.ruoyi.count.domain.StudentScore;
import com.ruoyi.count.domain.StudentStatistics;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.commons.math3.distribution.NormalDistribution;


import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 尹欣雨
 * @verdion 520
 * 21:00
 */


public class StatisticsCalculator {

    /**
     * 计算保留两位小数
     * @param value
     * @return
     */
    private static double roundToTwoDecimals(double value) {
        BigDecimal bd = BigDecimal.valueOf(value);
        return bd.setScale(2, RoundingMode.HALF_UP).doubleValue();
    }

    /**
     * 学生个人成绩计算
     * @param studentScoresList
     * @param weights
     * @return
     * @throws JsonProcessingException
     */
    static public List<StudentStatistics> calculateZScores(List<StudentScore> studentScoresList, Map<String, Long> weights) throws JsonProcessingException {
        System.out.println("学生分数");
        System.out.println(studentScoresList);
        Map<String, List<Long>> allScores = new HashMap<>();
        // 收集所有学生的分数
        for (StudentScore studentScores : studentScoresList) {
            for (Map.Entry<String, Long> entry : studentScores.getScores().entrySet()) {
                String indicatorId = entry.getKey();
                Long score = entry.getValue();
                allScores.computeIfAbsent(indicatorId, k -> new ArrayList<>()).add(score);
            }
        }

        // 计算每个指标的平均值和标准差
        Map<String, Double> averages = new HashMap<>();
        Map<String, Double> stdDevs = new HashMap<>();

        for (Map.Entry<String, List<Long>> entry : allScores.entrySet()) {
            String indicatorId = entry.getKey();
            List<Long> scores = entry.getValue();
            double average = roundToTwoDecimals(scores.stream().mapToDouble(Long::doubleValue).average().orElse(0));
            double variance = scores.size() > 1 ? roundToTwoDecimals(scores.stream().mapToDouble(s -> Math.pow(s - average, 2)).sum() / (scores.size() - 1)) : 0;
            double stdDev = roundToTwoDecimals(Math.sqrt(variance));

            averages.put(indicatorId, average);
            stdDevs.put(indicatorId, stdDev);
        }

        ObjectMapper objectMapper = new ObjectMapper();
        List<StudentStatistics> results = new ArrayList<>();

        for (StudentScore studentScores : studentScoresList) {
            Map<String, Double> zScores = new HashMap<>();
            Map<String, Integer> standardScores = new HashMap<>();

            // 计算三级指标的Z分数和标准分数
            for (Map.Entry<String, Long> entry : studentScores.getScores().entrySet()) {
                String indicatorId = entry.getKey();
                Long score = entry.getValue();
                Long weight = weights.get(indicatorId);

                if (weight != null) {
                    double average = averages.getOrDefault(indicatorId, 0.0);
                    double stdDev = stdDevs.getOrDefault(indicatorId, 1.0);
                    double zScore = stdDev != 0 ? roundToTwoDecimals((score - average) / stdDev) : 0;
                    int standardScore = Math.round((float) (zScore * 2 + 5));

                    zScores.put(indicatorId, zScore);
                    standardScores.put(indicatorId, standardScore);
                }
            }

            // 计算二级指标的Z分数
            Map<String, Double> secondaryZScores = new HashMap<>();
            Map<String, Long> secondaryWeights = new HashMap<>();
            for (String zIndicatorId : zScores.keySet()) {
                String secondaryId = zIndicatorId.substring(0, zIndicatorId.lastIndexOf('.')); // 获取二级指标ID
                secondaryZScores.put(secondaryId, secondaryZScores.getOrDefault(secondaryId, 0.0) + zScores.get(zIndicatorId) * weights.get(zIndicatorId));
                secondaryWeights.put(secondaryId, secondaryWeights.getOrDefault(secondaryId, 0L) + weights.get(zIndicatorId));
            }
            for (String secondaryId : secondaryZScores.keySet()) {
                double zScore = secondaryWeights.get(secondaryId) != 0 ? roundToTwoDecimals(secondaryZScores.get(secondaryId) / secondaryWeights.get(secondaryId)) : 0;
                zScores.put(secondaryId, zScore); // 更新二级指标的Z分数
                standardScores.put(secondaryId, Math.round((float) (zScore * 2 + 5)));
            }

            // 计算一级指标的Z分数
            Map<String, Double> primaryZScores = new HashMap<>();
            Map<String, Long> primaryWeights = new HashMap<>();

            for (String zIndicatorId : zScores.keySet()) {
                // 仅使用二级指标的 Z 分数
                if (zIndicatorId.contains(".")) {
                    String secondaryId = zIndicatorId.substring(0, zIndicatorId.lastIndexOf('.')); // 获取二级指标ID
                    if (zScores.containsKey(secondaryId)) { // 确保只处理二级指标
                        String primaryId = secondaryId.substring(0, secondaryId.indexOf('.')); // 获取一级指标ID
                        primaryZScores.put(primaryId, primaryZScores.getOrDefault(primaryId, 0.0) + zScores.get(secondaryId) * weights.get(secondaryId));
                        primaryWeights.put(primaryId, primaryWeights.getOrDefault(primaryId, 0L) + weights.get(secondaryId));
                    }
                }
            }

            for (String primaryId : primaryZScores.keySet()) {
                double zScore = primaryWeights.get(primaryId) != 0 ? roundToTwoDecimals(primaryZScores.get(primaryId) / primaryWeights.get(primaryId)) : 0;
                zScores.put(primaryId, zScore); // 更新一级指标的Z分数
                standardScores.put(primaryId, Math.round((float) (zScore * 2 + 5)));
            }

            // 计算总指标的Z分数（仅基于一级指标）
            double totalZScore = 0.0;
            long totalWeight = 0L;

            for (String primaryId : primaryZScores.keySet()) {
                double zScore = zScores.get(primaryId); // 获取一级指标的Z分数
                long weight = weights.get(primaryId); // 获取一级指标的权重
                totalZScore += zScore * weight; // 加权累加
                totalWeight += weight; // 累加权重
            }

            // 计算总指标的最终Z分数
            if (totalWeight != 0) {
                totalZScore = roundToTwoDecimals(totalZScore / totalWeight);
            } else {
                totalZScore = 0; // 避免除以零
            }


            // 更新总指标的Z分数
            zScores.put("totalIndicator", totalZScore); // 假设你用 "totalIndicator" 作为总指标的ID
            standardScores.put("totalIndicator", Math.round((float) (totalZScore * 2 + 5)));


            // 将 Z 分数和标准分数转换为 JSON 字符串
            String zScoresJson = objectMapper.writeValueAsString(zScores);
            String standardScoresJson = objectMapper.writeValueAsString(standardScores);

            results.add(new StudentStatistics(studentScores.getStudentId(), zScoresJson, standardScoresJson));
        }
        return results;
    }

    /**
     * 班级分数生成方法
     */
    public static ClassScoretemp generateClassScore( List<ClassScoretemp> students) {
        // 存储每个指标的总和Zscore
        Map<String, Double> totalZscore = new HashMap<>();
        Map<String, Integer> totalStrandScore = new HashMap<>();
        Map<String, Double> transformScore = new HashMap<>();

        for (ClassScoretemp element : students) {
            // 使用 JsonParser 解析 JSON 字符串  转换为 JsonObject
            JsonObject Zscore = JsonParser.parseString(element.getZscore()).getAsJsonObject();
            JsonObject strandScore = JsonParser.parseString(element.getStrandScore()).getAsJsonObject();

            for (Map.Entry<String, JsonElement> entry : Zscore.entrySet()) {
                String indicator = entry.getKey();
                double zscore = entry.getValue().getAsDouble();
                // 更新每个指标的总和
                totalZscore.put(indicator, totalZscore.getOrDefault(indicator, 0.0) + zscore);
            }

            for (Map.Entry<String, JsonElement> entry : strandScore.entrySet()) {
                String indicator = entry.getKey();
                int strand = strandScore.get(indicator).getAsInt();
                // 更新每个指标的总和
                totalStrandScore.put(indicator, totalStrandScore.getOrDefault(indicator, 0) + strand);
            }
        }
        // System.out.println(totalZscore);
        // System.out.println(totalStrandScore);
        int count = students.size();
        for (String indicator : totalZscore.keySet()) {
            double averageZscore = totalZscore.get(indicator) / count;
            totalZscore.put(indicator, roundToTwoDecimals(averageZscore));
            /**
             * NORM.DIST
             */
            // 创建一个均值为 0，标准差为 1 的正态分布
            NormalDistribution normalDist = new NormalDistribution(0, 1);
            double x = normalDist.cumulativeProbability(averageZscore);
            transformScore.put(indicator, roundToTwoDecimals(x));
        }
        for (String indicator : totalStrandScore.keySet()) {
            double averageZscore = (double) totalStrandScore.get(indicator) / count;
            totalStrandScore.put(indicator, (int) Math.round(averageZscore));
        }
        // System.out.println(totalZscore);
        // System.out.println(totalStrandScore);
        // 使用 Gson 序列化 Map 为合法的 JSON 字符串
        Gson gson = new Gson();
        String zscoreJson = gson.toJson(totalZscore);
        String strandScoreJson = gson.toJson(totalStrandScore);
        String transformScoreJson = gson.toJson(transformScore);

        // 创建一个新的 ClassScoretemp 对象并设置 JSON 字符串
        ClassScoretemp classScoretemp = new ClassScoretemp();
        classScoretemp.setStrandScore(strandScoreJson);  // 存储 JSON 字符串
        classScoretemp.setZscore(zscoreJson);  // 存储 JSON 字符串
        classScoretemp.setTransformScore(transformScoreJson);  // 存储 JSON 字符串
        return classScoretemp;
    }
}
